home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d21
/
byload.arc
/
BYLOAD.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-09-30
|
5KB
|
170 lines
/******** DESQVIEW/TOPVIEW LOADER FOR BOYAN VERSION D3 ********/
/*
** Written in Turbo C v1.5 small memory model by John Navas.
*/
char banner[] = "by-load v1.0 " __DATE__ " " __TIME__
"\r\nCopyright 1988 John Navas II, All Rights Reserved.\r\n";
#include <io.h>
#include <dos.h>
#include <mem.h>
#include <process.h>
unsigned _heaplen = 512; /* small heap */
unsigned _stklen = 1024; /* small stack */
#define MONOTXT 7 /* monochrome text mode */
#define MDASEG 0xB000 /* monochrome video segment */
#define CGASEG 0xB800 /* color video segment */
#define RLO(x) (((unsigned char*)&x)[0]) /* bytes in a word */
#define RHI(x) (((unsigned char*)&x)[1])
typedef void(interrupt far*INTVEC)(); /* interrupt vector */
typedef void(interrupt far*far*INTPTR)(); /* interrupt vectors */
#define MKINTPTR(n) (&((INTPTR)0L)[n]) /* make pointer to int vec */
#define WR_STRC(f,s) _write(f,s,sizeof(s)-1) /* string constant */
#define STDERR 2 /* predefined level 1 file */
#define SE_STRC(s) WR_STRC(STDERR,s) /* string con to STDERR */
#define BIOSVID 0x10 /* BIOS video interrupt */
#define GETVIDMOD 0x0F /* get video mode */
#define GETVIDBUF 0xFE /* get video buffer */
#define DOSINT 0x21 /* DOS interrupt number */
#define OFFSET (0x993F-0x9424) /* offset of patch in overlay */
void interrupt (*dosvec)(); /* DOS interrupt vector */
char vidmod; /* video mode */
unsigned vidseg; /* TopView video buffer segment */
typedef struct { /* data structure to patch */
char a;
unsigned mda;
char b[13];
unsigned cga;
} PATCH;
PATCH pat = { /* data pattern to match */
0xB8,
MDASEG,
{
0xA3, 0x0E, 0x19,
0xB8, 0x00, 0x00,
0xA2, 0x41, 0x1B,
0xE9, 0x15, 0x00,
0xB8 },
CGASEG
};
PATCH dat; /* patch work area */
INTVEC pascal GETVECT(unsigned intnum) /* GET INT VECTOR */
{
INTVEC adr;
disable();
adr = *MKINTPTR( intnum );
enable();
return adr;
}
void pascal SETVECT( unsigned intnum, INTVEC adr ) /* SET INT VECTOR */
{
disable();
*MKINTPTR( intnum ) = adr;
enable();
}
struct INTREGS { /* interrupt routine registers */
unsigned bp_, di_, si_, ds_, es_, dx_;
unsigned cx_, bx_, ax_, ip_, cs_, flags_;
};
struct INTREGS pascal CHAININT(void (interrupt far *vec)(), struct INTREGS r)
{
asm push ds ;
asm mov ax,r.ax_ ;
asm mov bx,r.bx_ ;
asm mov cx,r.cx_ ;
asm mov dx,r.dx_ ;
asm mov si,r.si_ ;
asm mov di,r.di_ ;
asm mov ds,r.ds_ ;
asm mov es,r.es_ ;
asm pushf ;
asm cli ;
asm call dword ptr[vec] ;
asm pushf ;
asm mov r.ax_,ax ;
asm mov r.bx_,bx ;
asm mov r.cx_,cx ;
asm mov r.dx_,dx ;
asm mov r.si_,si ;
asm mov r.di_,di ;
asm mov r.ds_,ds ;
asm mov r.es_,es ;
asm pop r.flags_ ;
asm pop ds ;
return r;
}
void interrupt intentry( struct INTREGS cr ) /* INTERRUPT ENTRY POINT */
{
struct INTREGS rr; /* save entry registers */
enable(); /* allow interrupts */
cr = CHAININT( dosvec, rr = cr ); /* chain to DOS */
if ( RHI( rr.ax_ ) == 0x3F && rr.cx_ == 0x2200 ) { /* read overlay */
dat = *(PATCH far*)MK_FP( rr.ds_, rr.dx_ + OFFSET );
if ( ! memcmp( (char*)&dat, (char*)&pat, sizeof(pat) ) ) {
if ( vidmod == MONOTXT )
dat.mda = vidseg; /* monochrome */
else
dat.cga = vidseg; /* color */
*(PATCH far*)MK_FP( rr.ds_, rr.dx_ + OFFSET ) = dat;
}
else
SE_STRC( "\aWRONG BOYAN VERSION\r\n" );
SETVECT( DOSINT, dosvec ); /* restore DOS interrupt vector */
}
}
int pascal GETMOD( void ) /* GET VIDEO MODE */
{
struct REGPACK r;
RHI( r.r_ax ) = GETVIDMOD;
intr( BIOSVID, &r );
return RLO( r.r_ax );
}
unsigned pascal GETSEG( int mod ) /* GET TOPVIEW VIDEO BUFFER */
{
struct REGPACK r;
r.r_es = mod == MONOTXT ? MDASEG : CGASEG ; /* segment */
r.r_di = 0; /* offset */
RHI( r.r_ax ) = GETVIDBUF;
intr( BIOSVID, &r );
if ( r.r_di & 15 ) {
SE_STRC( "\aVIDEO BUFFER BOUNDARY ERROR\r\n" );
exit( -1 );
}
return r.r_es + ( r.r_di >> 4 );
}
main( int ac, char **av )
{
int ret;
SE_STRC( banner );
if ( ac < 2 ) {
SE_STRC( "usage: pathname [arg...]\r\n" );
return -1;
}
vidseg = GETSEG( vidmod = GETMOD() ); /* get video segment */
dosvec = GETVECT( DOSINT ); /* save DOS interrupt vector */
SETVECT( DOSINT, intentry ); /* setup my interrupt vector */
if ( (ret = spawnv(P_WAIT, av[1], av + 1) ) == -1 )
SE_STRC( "\aCANNOT RUN PROGRAM\r\n" );
SETVECT( DOSINT, dosvec ); /* restore DOS interrupt vector */
return ret;
}